package com.hjk.common.utils.collection;

import cn.hutool.core.lang.Assert;
import com.google.common.collect.Lists;
import com.hjk.common.utils.check.Check;
import org.apache.commons.lang3.ObjectUtils;
import org.checkerframework.checker.units.qual.K;
import org.junit.Test;

import java.text.Collator;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 集合相关工具类
 *
 * @author huangjunkai
 */
public class CollectUtils {
    /**
     * 排序 倒序
     *
     * @param list
     * @param keyExtractor
     * @param <T>
     * @param <U>
     */
    @SuppressWarnings("unchecked")
    public void sort(List list, Function keyExtractor) {
        list.sort(Comparator.comparing(keyExtractor, Comparator.nullsFirst(Comparator.naturalOrder())).reversed());
    }

    /**
     * 中文排序
     *
     * @param list
     * @param keyExtractor
     */

    public void sortChina(List list, Function keyExtractor) {
        list.sort(Comparator.comparing(keyExtractor, Comparator.nullsFirst(Collator.getInstance(Locale.CHINA)).reversed()));
    }

    public void sort(List list, Function number, Function china) {
        list.sort(
                Comparator
                        .comparing(number, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .reversed()
                        .thenComparing(china, Comparator.nullsFirst(Collator.getInstance(Locale.CHINA)))
        );
    }


    @Test
    public void test2343() {
        System.out.println("");
        List<Integer> list = Arrays.asList(1, 234, 2342, 3454353, 45, 43);
        sort(list, f -> f);
        System.out.println(list);
    }

    /**
     * newMap
     *
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> newMap() {
        return new HashMap<>();
    }

    /**
     * newMap
     *
     * @param <K>
     * @param <V>
     * @return
     */
    public static <K, V> Map<K, V> newMap(int initialCapacity) {
        return new HashMap<>(initialCapacity);
    }


    public static <T> List<T> newList() {
        return new ArrayList<>();
    }

    public static <T> List<T> newList(int size) {
        return new ArrayList<>(size);
    }

    public static <T> Set<T> newSet() {
        return new HashSet<>();
    }

    public static <E> List<E> newLinkedList() {
        return new LinkedList<>();
    }

    public static <T> void addAll(List<T> list, List<T>... lists) {
        if (ObjectUtils.isNotEmpty(list)) {
            Arrays.stream(lists).filter(ObjectUtils::isNotEmpty).peek(list::addAll);
        }
    }


    @Test
    public void test2() {
        List<String> list = CollectUtils.newList();
        list.add("jj");


        ArrayList<Object> objects = Lists.newArrayList();
    }

    /**
     * 返回a+b的新List. 并集
     *
     * @param a 集合 a
     * @param b 集合 b
     * @return 合并后的集合
     */
    public static <T> List<T> union(final Collection<T> a, final Collection<T> b) {
        List<T> result = new ArrayList<>(a);
        result.addAll(b);
        return result;
    }

    /**
     * 返回a-b的新List. 差集
     *
     * @param a 集合 a
     * @param b 集合 b
     * @return 差集的集合
     */
    public static <T> List<T> subtract(final Collection<T> a, final Collection<T> b) {
        List<T> list = new ArrayList<>(a);
        for (T element : b) {
            list.remove(element);
        }
        return list;
    }


    /**
     * 返回a与b的交集的新List.
     *
     * @param a 集合 a
     * @param b 集合 b
     * @return 交集的集合
     */
    public static <T> List<T> intersection(Collection<T> a, Collection<T> b) {
        return a.stream().filter(b::contains).collect(Collectors.toList());
       /* List<T> list = new ArrayList<>();
        for (T element : a) {
            if (b.contains(element)) {
                list.add(element);
            }
        }
        return list;*/
    }


    /**
     * 返回a与b的笛卡尔积
     *
     * @param a 集合 a
     * @param b 集合 b
     * @return 笛卡尔积
     */
    public static <T> Map<T, T> cartesian(Collection<T> a, Collection<T> b) {
        List<T> list1 = new ArrayList<>(a);
        List<T> list2 = new ArrayList<>(b);
        Map<T, T> map = new HashMap<>(list1.size() * list2.size());
        for (T t1 : list1) {
            for (T t2 : list2) {
                map.put(t1, t2);
            }
        }
        return map;
    }

    /**
     * 将两个list组合成Key/Value形式的,这里默认两个集合的元素数量都相同，否则会抛出异常。
     *
     * @param a 集合 a
     * @param b 集合 b
     * @return map key是集合1的元素,value是集合2的元素
     */
    public static <T> Map<T, T> zip(Collection<T> a, Collection<T> b) {
        int size = a.size();
        Assert.isTrue(size == b.size(), "集合长度不一致");
        List<T> list1 = new ArrayList<>(a);
        List<T> list2 = new ArrayList<>(b);
        Map<T, T> map = new HashMap<>(list1.size());
        for (int i = 0; i < size; i++) {
            map.put(list1.get(i), list2.get(i));
        }
        return map;
    }

    /**
     * 集合切割  效率差
     *
     * @param tList 需要切割的集合
     * @param size  每个集合大小
     * @return 切割后的双重集合
     */
    @Deprecated
    public static <T> List<List<T>> splitCollection(List<T> tList, int size) {
        if (ObjectUtils.isEmpty(tList) || size < 0) {
            return null;
        }
        List<List<T>> result = new ArrayList<>();
        if (tList.size() <= size) {
            result.add(tList);
        } else {
            int count = 0;
            List<T> subCollection = null;
            for (T id : tList) {
                if (subCollection == null) {
                    subCollection = new ArrayList<>();
                    result.add(subCollection);
                }
                subCollection.add(id);
                count++;
                if (count == size) {
                    count = 0;
                    subCollection = null;
                }
            }
        }
        return result;
    }

    /**
     * 集合切割
     *
     * @param list 需要切割的集合
     * @param len  每个集合大小
     * @return 切割后的双重集合
     */
    public static <T> List<List<T>> splitList(List<T> list, int len) {
        if (ObjectUtils.isEmpty(list) || len < 1) {
            return null;
        }

        List<List<T>> result = new ArrayList<>();

        int size = list.size();
        //切割集合次数  效率高
        int count = (size + len - 1) / len;
        //低效率
        //int count = (Math.ceil(size * 1.0 / len));

        for (int i = 0; i < count; i++) {
            //Math.min最后一个集合不到切割len大小
            List<T> subList = list.subList(i * len, (Math.min((i + 1) * len, size)));
            result.add(subList);
        }
        return result;
    }

    public static void main(String[] args) {

        List<Integer> jsonNodeList = new ArrayList<>();

        for (int i = 0; i < 100000000; i++) {
            jsonNodeList.add(i);
        }
        long start = System.currentTimeMillis();//开始时间
        List<List<Integer>> lists = CollectUtils.splitList(jsonNodeList, 100);
        long end = System.currentTimeMillis();//结束时间
        System.out.println("一共耗时" + (end - start) / 1000.0 + "s");

        List<List<Integer>> lists2 = CollectUtils.splitCollection(jsonNodeList, 100);
        long end2 = System.currentTimeMillis();//结束时间
        System.out.println("一共耗时" + (end2 - end) / 1000.0 + "s");
        System.out.println();


    }

}


